<template>
  <div class="map-container">
    <!-- 地图视图 -->
    <div
      v-if="!showPanorama"
      ref="mapContainer"
      style="width: 100%; height: 100vh"
      @mousedown="onMouseDown"
      @mousemove="onMouseMove"
      @mouseup="onMouseUp"
      @click="handleMarkerClick"
    ></div>

    <!-- 弹窗：展示点击点信息（封装组件） -->
    <MarkerInfoDialog v-model:visible="dialogVisible" :info="clickedInfo" />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
import MarkerInfoDialog from "./MarkerInfoDialog.vue";

/**
 * 多边形路径数据
 */
let polygonPath = ref<any[]>([
  { lng: 118.86502, lat: 32.15444 },
  { lng: 118.868834, lat: 32.154435 },
  { lng: 118.86944, lat: 32.156479 },
  { lng: 118.867032, lat: 32.156615 },
  { lng: 118.865712, lat: 32.156451 },
]);

/**
 * 地图中心点
 */
const center = ref({ lng: 118.86736697300944, lat: 32.15547503595335 });

/**
 * 地图缩放级别
 */
const zoom = ref(18);

/**
 * 是否显示全景
 */
const showPanorama = ref<boolean>(false);

/**
 * 地图实例
 */
let mapInstance: any = null;

/**
 * 高德地图API引用
 */
let AMap: any = null;

/**
 * 多边形实例
 */
let polygonInstance: any = null;

/**
 * 地图容器引用
 */
const mapContainer = ref<HTMLElement | null>(null);

/**
 * 单击/双击冲突控制
 */
let singleClickTimer: any = null;
const SINGLE_CLICK_DELAY_MS = 250;

// 地图移动状态，移动中不处理点击
let isMapMoving: boolean = false;

// 鼠标拖动距离阈值抑制点击放大
let isPointerDown: boolean = false;
let startClientX = 0;
let startClientY = 0;
let movedBeyondThreshold = false;
const CLICK_MOVE_THRESHOLD_PX = 5;

/**
 * 记录按下位置
 */
const onMouseDown = (e: MouseEvent) => {
  isPointerDown = true;
  movedBeyondThreshold = false;
  startClientX = e.clientX;
  startClientY = e.clientY;
};

/**
 * 统计移动距离，超过阈值则标记为拖动
 */
const onMouseMove = (e: MouseEvent) => {
  if (!isPointerDown) return;
  if (movedBeyondThreshold) return;
  const dx = Math.abs(e.clientX - startClientX);
  const dy = Math.abs(e.clientY - startClientY);
  if (dx > CLICK_MOVE_THRESHOLD_PX || dy > CLICK_MOVE_THRESHOLD_PX) {
    movedBeyondThreshold = true;
  }
};

/**
 * 抬起时结束拖动状态
 */
const onMouseUp = () => {
  isPointerDown = false;
};

/**
 * 更新多边形路径
 * @param path 新的路径数据
 */
const updatePolygonPath = (path: any[]) => {
  polygonPath.value = path;
  if (polygonInstance) {
    polygonInstance.setPath(path);
  }
};

/**
 * 让地图视野适配多边形范围
 * 功能：避免因中心点在其他城市导致多边形不可见
 */
const fitPolygonViewport = () => {
  if (!mapInstance || !AMap) return;
  if (!polygonPath.value || polygonPath.value.length === 0) return;

  try {
    const bounds = new (window as any).AMap.Bounds();
    polygonPath.value.forEach((point) => {
      bounds.extend(new (window as any).AMap.LngLat(point.lng, point.lat));
    });

    mapInstance.setBounds(bounds);
  } catch (e) {
    console.warn("fitPolygonViewport error", e);
  }
};

/**
 * 地图初始化完成回调
 */
const initMap = () => {
  if (!mapContainer.value || !(window as any).AMap) {
    console.error("地图容器或AMap API未加载");
    return;
  }

  console.log("开始初始化高德地图");

  // 创建地图实例
  mapInstance = new (window as any).AMap.Map(mapContainer.value, {
    center: [center.value.lng, center.value.lat],
    zoom: zoom.value,
    mapStyle: "amap://styles/satellite", // 强制使用卫星图
    viewMode: "3D", // 启用3D视图
    pitch: 0, // 俯仰角
    rotation: 0, // 旋转角度
    layers: [
      new (window as any).AMap.TileLayer.Satellite({ zIndex: 20 }), // 添加卫星图层并设置zIndex为20
      new (window as any).AMap.TileLayer.RoadNet(), // 添加路网图层
    ],
  });

  // 创建多边形
  polygonInstance = new (window as any).AMap.Polygon({
    path: polygonPath.value.map((point) => [point.lng, point.lat]),
    strokeColor: "#FF5722",
    strokeOpacity: 0.9,
    strokeWeight: 3,
    fillColor: "#FF7043",
    fillOpacity: 0.25,
    editable: true,
  });

  // 添加多边形到地图
  mapInstance.add(polygonInstance);

  // 监听多边形编辑事件
  (window as any).AMap.event.addListener(
    polygonInstance,
    "pathchange",
    (e: any) => {
      const path = e.target.getPath().map((point: any) => ({
        lng: point.lng,
        lat: point.lat,
      }));
      updatePolygonPath(path);
    }
  );

  // 让视野适配多边形
  fitPolygonViewport();

  // 监听地图移动，移动中不触发点击逻辑
  if ((window as any).AMap && mapInstance) {
    (window as any).AMap.event.addListener(mapInstance, "movestart", () => {
      isMapMoving = true;
    });
    (window as any).AMap.event.addListener(mapInstance, "moveend", () => {
      // 延迟一个tick，避免moveend紧接着产生的点击
      setTimeout(() => {
        isMapMoving = false;
      }, 0);
    });
  }

  console.log("高德地图初始化成功");
};

/**
 * 处理标注点击事件
 * @param event 点击事件
 */
const handleMarkerClick = (event: any) => {
  // 地图正在移动或发生拖动时不处理点击
  if (isMapMoving || movedBeyondThreshold) {
    // 重置一次性标志，避免后续点击被误伤
    movedBeyondThreshold = false;
    return;
  }
  if (singleClickTimer) {
    clearTimeout(singleClickTimer);
    singleClickTimer = null;
  }
  singleClickTimer = setTimeout(() => {
    // 从DOM事件中获取鼠标点击位置
    const rect = mapContainer.value?.getBoundingClientRect();
    if (!rect) return;

    // 计算相对于地图容器的坐标
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;

    // 将屏幕坐标转换为地理坐标
    const lngLat = mapInstance.containerToLngLat(
      new (window as any).AMap.Pixel(x, y)
    );

    const lng = lngLat.lng;
    const lat = lngLat.lat;
    const name = "点击位置";
    if (typeof lng === "number" && typeof lat === "number") {
      // 若当前缩放小于20，则先缩放到20并居中，不弹窗
      const currentZoom =
        typeof mapInstance?.getZoom === "function"
          ? mapInstance.getZoom()
          : undefined;
      const centerArr = [lng, lat];
      if (typeof currentZoom === "number" && currentZoom < 20) {
        if (typeof mapInstance?.setZoomAndCenter === "function") {
          mapInstance.setZoomAndCenter(20, centerArr);
        } else {
          if (typeof mapInstance?.panTo === "function")
            mapInstance.panTo(centerArr);
          if (typeof mapInstance?.setZoom === "function")
            mapInstance.setZoom(20);
        }
        // 首次点击仅缩放与居中
      } else {
        // 已经是20级，再次点击才弹窗
        clickedInfo.value = { name, lng, lat };
        dialogVisible.value = true;
      }
    }
    singleClickTimer = null;
  }, SINGLE_CLICK_DELAY_MS);
};

/**
 * 弹窗显示状态
 */
const dialogVisible = ref<boolean>(false);

/**
 * 点击点信息
 */
const clickedInfo = ref<{ name: string; lng: number; lat: number } | null>(
  null
);

/**
 * 加载高德地图API
 */
const loadAMapAPI = (): Promise<void> => {
  return new Promise((resolve, reject) => {
    if ((window as any).AMap) {
      resolve();
      return;
    }

    const script = document.createElement("script");
    script.type = "text/javascript";
    script.src = `https://webapi.amap.com/maps?v=2.0&key=8e4b86efc4b42bef72e623e5a5e646fe&plugin=AMap.PolygonEditor`;
    script.onload = () => {
      console.log("高德地图API加载成功");
      resolve();
    };
    script.onerror = () => {
      console.error("高德地图API加载失败");
      reject(new Error("高德地图API加载失败"));
    };
    document.head.appendChild(script);
  });
};

/**
 * 组件挂载时初始化地图
 */
onMounted(async () => {
  try {
    await loadAMapAPI();
    AMap = (window as any).AMap;
    initMap();
  } catch (error) {
    console.error("地图初始化失败:", error);
  }
});

/**
 * 组件卸载时清理资源
 */
onUnmounted(() => {
  if (singleClickTimer) {
    clearTimeout(singleClickTimer);
  }
  if (mapInstance) {
    mapInstance.destroy();
  }
});
</script>

<style scoped>
.map-container {
  width: 100vw;
  height: 100vh;
  position: relative;
  overflow: hidden;
}

.panorama-viewer {
  width: 100%;
  height: 100vh;
}

.info-panel {
  position: absolute;
  top: 20px;
  left: 20px;
  background: rgba(255, 255, 255, 0.95);
  padding: 20px;
  border-radius: 10px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  z-index: 1000;
  min-width: 280px;
  max-height: 85vh;
  overflow-y: auto;
}

.info-panel h2 {
  margin: 0 0 15px 0;
  color: #333;
  font-size: 20px;
}

.info-panel h3 {
  margin: 15px 0 10px 0;
  color: #555;
  font-size: 16px;
  border-bottom: 2px solid #4caf50;
  padding-bottom: 5px;
}

.control-group {
  margin-bottom: 15px;
}

.map-type-buttons {
  display: flex;
  gap: 10px;
}

.map-type-btn {
  flex: 1;
  padding: 10px 15px;
  margin: 0;
  background: #e0e0e0;
  color: #666;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s ease;
  font-weight: 500;
}

.map-type-btn:hover {
  background: #d0d0d0;
}

.map-type-btn.active {
  background: #4caf50;
  color: white;
}

.map-type-btn.active.satellite-btn {
  background: #2196f3;
}

.poi-list {
  max-height: 200px;
  overflow-y: auto;
}

.poi-btn {
  padding: 10px 15px;
  margin: 5px 0;
  background: #f5f5f5;
  color: #333;
  border: 1px solid #ddd;
  border-radius: 5px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s ease;
  width: 100%;
  text-align: left;
}

.poi-btn:hover {
  background: #4caf50;
  color: white;
  transform: translateX(5px);
  border-color: #4caf50;
}

.back-btn {
  padding: 12px 20px;
  margin: 5px 0;
  background: #ff9800;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s ease;
  width: 100%;
  text-align: center;
}

.back-btn:hover {
  background: #f57c00;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.indoor-btn {
  padding: 10px 15px;
  margin: 5px 0;
  background: #2196f3;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s ease;
  width: 100%;
  text-align: center;
}

.indoor-btn:hover {
  background: #1976d2;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.panorama-btn {
  margin-top: 5px;
  padding: 5px 10px;
  background: #4caf50;
  color: white;
  border: none;
  border-radius: 3px;
  cursor: pointer;
}

.status {
  margin-top: 15px;
  padding: 10px;
  background: #f5f5f5;
  border-radius: 5px;
}

.status p {
  margin: 0;
  color: #666;
  font-size: 13px;
  line-height: 1.6;
}

.tips {
  margin-top: 15px;
  padding: 10px;
  background: #e3f2fd;
  border-left: 4px solid #2196f3;
  border-radius: 5px;
}

.tip {
  margin: 0;
  color: #1565c0;
  font-size: 12px;
  line-height: 1.6;
}

@media (max-width: 768px) {
  .info-panel {
    top: 10px;
    left: 10px;
    right: 10px;
    width: auto;
    min-width: auto;
  }

  .map-type-buttons {
    flex-direction: column;
  }

  .poi-list {
    max-height: 150px;
  }
}
</style>
